/**
 * 
 */
package info.niwota.web.apache;

import info.niwota.web.ApplicationContext;
import info.niwota.web.Debug;
import info.niwota.web.ImageUtils;
import info.niwota.web.JSONUtil;
import info.niwota.web.NVPair;
import info.niwota.web.Preferences;
import info.niwota.web.SessionManager;
import info.niwota.web.proxy.PeerRoute;
import info.niwota.web.proxy.ServerSocketThread;

import java.io.File;
import java.util.List;
import java.util.Set;

import jvs.peer.io.ChannelManager;

import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.json.JSONObject;

import x.org.apache.http.HttpRequest;
import x.org.apache.http.HttpResponse;
import x.org.apache.http.protocol.HttpContext;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.net.Uri;
import android.util.Log;

/**
 * @author qiangli
 * 
 */
public class BinHandler extends BaseHandler {

	private static final int THUMBNAIL_WIDTH = 160;

	private static final int THUMBNAIL_HEIGHT = 160;

	private static final String TAG = "BinHandler";

	public BinHandler(Context ctx) {
		super(ctx);
	}

	@Override
	public boolean handle(String path, HttpRequest req, HttpResponse res,
			HttpContext context) throws Exception {
		if (!path.startsWith("/bin/")) {
			return false;
		}
		final Uri uri = Uri.parse("uri:" + path);
		final String p = uri.getPath();
		if (Debug.DEBUG) {
			Log.d(TAG, "handle: " + p);
		}
		if (p.startsWith("/bin/file/upload")) {
			@SuppressWarnings("unchecked")
			List<NVPair> params = (List<NVPair>) context
					.getAttribute(BaseHandler.PARAMETERS_KEY);
			JSONObject data = new JSONObject();
			for (NVPair nvp : params) {
				data.put(nvp.getName(), nvp.getValue());
			}
			sendJSONData(req, res, context, data);
			return true;
		}
		if (p.startsWith("/bin/file/remove")) {
			String fileuri = uri.getQueryParameter("uri");
			Uri u = Uri.parse(fileuri);
			if (Debug.DEBUG) {
				Log.d(TAG, " file uri: " + u);
			}
			String fname = u.getPath();
			File tempDir = ApplicationContext.getTempDir(ctx);
			File f = new File(tempDir, fname);
			if (Debug.DEBUG) {
				Log.d(TAG, " file: " + f);
			}
			//
			boolean result = false;
			if (f.exists()) {
				result = f.delete();
			}
			JSONObject data = new JSONObject();
			data.put("result", result);
			sendJSONData(req, res, context, data);
			return true;
		}
		if (p.startsWith("/bin/thumb")) {
			String fileuri = uri.getQueryParameter("uri");
			Uri nu = Uri.parse(fileuri);
			// save orginal
			final String cp = cachePath(nu);	
			if (Debug.DEBUG) {
				Log.d(TAG, "Cache path uri: " + nu + " path: " + cp);
			}
			File f = getCacheFile(cp);
			boolean tooOld = ApplicationContext.isTooOld(f);
			if (!f.exists() || tooOld) {
				copy(nu, f, true);
				if (Debug.DEBUG) {
					Log.d(TAG, "cached uri: " + nu + " file: " + f);
				}
			}
			// create thumb
			int width = parseInt(uri.getQueryParameter("width"),
					THUMBNAIL_WIDTH);
			int height = parseInt(uri.getQueryParameter("height"),
					THUMBNAIL_HEIGHT);
			//
			final String tp = thumbfolder(width, height) + "/" + cp; 
			if (Debug.DEBUG) {
				Log.d(TAG, "thumb path uri: " + nu + " path: " + tp);
			}
			File tf = getCacheFile(tp);
			if (!tf.exists() || tooOld) {
				ImageUtils.thumbnail(f, tf, width, height, true);
				if (Debug.DEBUG) {
					Log.d(TAG, "thumbnail cached uri: " + nu + " file: " + tf);
				}
			}
			sendFile(req, res, tf, IMAGE_ANY);
			return true;
		}
		if (p.startsWith("/bin/site/info")) {
			//same as /siteinfo of ResourceHandler
			JSONObject data = Preferences.getSiteInfo(ctx);
			sendJSONData(req, res, context, data);
			return true;
		}
		if (p.startsWith("/bin/site/bluetooth")) {
			BluetoothAdapter adp = BluetoothAdapter.getDefaultAdapter();
			Set<BluetoothDevice> devices = ApplicationContext.getBluetoothDevices();
			JSONObject data = JSONUtil.toJson(adp, devices);
			sendJSONData(req, res, context, data);
			return true;
		}
		if (p.startsWith("/bin/site/wifi")) {
			//TODO
		}
		if (p.startsWith("/bin/site/peer")) {
			JSONObject data = new JSONObject();
			final ChannelManager manager = ApplicationContext.getChannelManager();	
			data.put("jid", manager.getJid());
			data.put("ip", manager.getIp());
			data.put("port", manager.getPort());
			data.put("peers", ApplicationContext.getPeers(ctx));
			sendJSONData(req, res, context, data);
			return true;
		}
		if (p.startsWith("/bin/connect")) {
			handleConnect(uri, context, req, res);
		}
		//
		return true;
	}

	/**
	 * thumb/[width]x[height]
	 * 
	 * @param width
	 * @param height
	 * @return
	 */
	private String thumbfolder(int width, int height) {
		return "thumb/" + width + "x" + height;
	}
	
	private boolean handleConnect(Uri uri, HttpContext context,
			HttpRequest request, HttpResponse response) throws Exception {
		
		final String realm = uri.getQueryParameter("realm");
		final String address = uri.getQueryParameter("address");
		
		final GenericKeyedObjectPool pool = PeerRoute.get(realm);
		
		ServerSocketThread obj = null;
		
		if (Debug.DEBUG) {
			Log.d(TAG, "handleConnect realm: " + realm + " address: " + address + " " + pool);
		}
		
		try {
			obj = (ServerSocketThread) pool.borrowObject(address);
			
			final String ip = (String) context.getAttribute(SessionManager.WEB_HOST_KEY); //WiFi.getIp(ctx);
			final String location = "http://"+ (ip == null ? "localhost" : ip) +":"+obj.getPort();
			
			sendRedirect(response, location);
			
			if (Debug.DEBUG) {
				Log.d(TAG, "handleConnect redirected: " + location);
			}
		} catch (Exception e) {
			pool.invalidateObject(address, obj);
			
			e.printStackTrace();
		} finally {
			if (obj != null) {
				pool.returnObject(address, obj);
			}
		}
		return true;
	}

}
